﻿#define _CRT_SECURE_NO_WARNINGS 1

#include <iostream>
#include <queue>
#include <climits>
#include <vector>
#include <tuple>
using namespace std;

int m, n;
vector<vector<int>> vec;
int dx[4] = { 0,0,-1,1 };
int dy[4] = { -1,1,0,0 };
vector<int> exist;

int dfs(int posI, int posJ)
{
    if (exist[posI * n + posJ])
    {
        return exist[posI * n + posJ];
    }

    int len = 1;
    for (int k = 0; k < 4; ++k)
    {
        int newI = posI + dx[k];
        int newJ = posJ + dy[k];
        if (newI >= 0 && newI < m && newJ >= 0 && newJ < n && vec[posI][posJ] > vec[newI][newJ])
        {
            len = max(len, dfs(newI, newJ) + 1);
        }
    }

    exist[posI * n + posJ] = len;
    return exist[posI * n + posJ];
}

int main()
{
    cin >> m >> n;
    vec.assign(m, vector<int>(n, 0));
    for (int i = 0; i < m; ++i)
    {
        for (int j = 0; j < n; ++j)
        {
            cin >> vec[i][j];
        }
    }

    exist.assign(m * n, 0);
    int result = 0;
    for (int i = 0; i < m; ++i)
    {
        for (int j = 0; j < n; ++j)
        {
            result = max(result, dfs(i, j));
        }
    }

    cout << result << endl;
    return 0;
}

/*
给定一个n×m的矩阵，矩阵中的数字表示滑雪场各个区域的高度，你可以选择从任意一个区域出发，并滑向任意一个周边的高度严格更低的区域（周边的定义是上下左右相邻的区域）。请问整个滑雪场中最长的滑道有多长？(滑道的定义是从一个点出发的一条高度递减的路线）。
(本题和矩阵最长递增路径类似，该题是当年NOIP的一道经典题)

数据范围：1≤n,m≤100 ，矩阵中的数字满足1≤val≤1000
输入描述：
第一行输入两个正整数 n 和 m 表示矩阵的长宽。
后续 n 行输入中每行有 m 个正整数，表示矩阵的各个元素大小。
输出描述：
输出最长递减路线。

示例1
输入：
5 5
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
复制
输出：
25
说明：
从25出发，每次滑向周边比当前小 1 的区域。 25->24->23->22->......->1
*/

